package dbrpc

import (
	"bytes"
	"database/sql"
	"dub/define/grpcmodel"
	"dub/utils"
	"fmt"
	"golang.org/x/net/context"
)

//与代理有关的数据库操作
type DbRpcAgent struct {
	log *utils.Logger
}

//修改代理信息
func (a *DbRpcAgent) Update(ctx context.Context, args *grpcmodel.ModelDbRpcAgentReqUpdate) (reply *grpcmodel.ModelDbRpcAgentResUpdate, err error) {
	reply = &grpcmodel.ModelDbRpcAgentResUpdate{}
	sql_buf := bytes.Buffer{}
	sql_buf.WriteString("update dubadvert set agEditTime=now()")
	params := make([]interface{}, 0)

	if args.GetIsAllUpdate() || (!args.GetIsAllUpdate() && args.GetModelDbRpcAgent().GetLoginName() != "") {
		sql_buf.WriteString(",aLoginName=?")
		params = append(params, args.GetModelDbRpcAgent().GetLoginName())
	}
	if args.GetIsAllUpdate() || (!args.GetIsAllUpdate() && args.GetModelDbRpcAgent().GetRegionCode() != "") {
		sql_buf.WriteString(",regionCode=?")
		params = append(params, args.GetModelDbRpcAgent().GetRegionCode())
	}
	if args.GetIsAllUpdate() || (!args.GetIsAllUpdate() && args.GetModelDbRpcAgent().GetAgentStatus() > 0) {
		sql_buf.WriteString(",agentStatus=?")
		params = append(params, args.GetModelDbRpcAgent().GetAgentStatus())
	}
	if args.GetIsAllUpdate() || (!args.GetIsAllUpdate() && args.GetModelDbRpcAgent().GetLoginPwd() != "") {
		sql_buf.WriteString(",aLoginPwd=?")
		params = append(params, args.GetModelDbRpcAgent().GetLoginPwd())
	}
	if args.GetIsAllUpdate() || (!args.GetIsAllUpdate() && args.GetModelDbRpcAgent().GetAgentPrice() > 0) {
		sql_buf.WriteString(",agentPrice=?")
		params = append(params, args.GetModelDbRpcAgent().GetAgentPrice())
	}
	sql_buf.WriteString(" where agentid=?")
	params = append(params, args.GetModelDbRpcAgent().GetAgentId())

	dbAccounts := NewDbProxy().Get(DB_Accounts)
	sql_str := sql_buf.String()
	a.log.Infof("def_func_db_agent.go Update method exec %s params is %+v\n", sql_str, params)
	res, err := dbAccounts.Exec(sql_buf.String(), params...)

	for {
		if err != nil {
			a.log.Infof("def_func_db_agent.go Update method dbAccounts.Exec err. %v\n", err)
			reply.Err = 2
			break
		}

		up_count, err := res.RowsAffected()
		if err != nil {
			a.log.Infof("def_func_db_agent.go Update method res.RowsAffected err. %v\n", err)
			reply.Err = 2
			break
		}
		if up_count < 1 {
			reply.Err = 1
		}
		reply.AgentId = args.GetModelDbRpcAgent().GetAgentId()
		break
	}
	return
}

//根据条件查询代理信息
func (a *DbRpcAgent) Find(ctx context.Context, args *grpcmodel.ModelDbRpcAgentReqFind) (reply *grpcmodel.ModelDbRpcAgentResFinds, err error) {
	reply = &grpcmodel.ModelDbRpcAgentResFinds{}
	after_from_buf := bytes.Buffer{}
	params := make([]interface{}, 0)
	after_from_buf.WriteString("from dubagent d left join dubuser u on d.addUseId=u.userId where d.agentStatus=1")

	for {
		if args.GetAddUseId() > 0 {
			after_from_buf.WriteString(" and d.addUseId=?")
			params = append(params, args.GetAddUseId())
		}

		dbAccounts := NewDbProxy().Get(DB_Accounts)
		if args.GetIsPage() && args.GetPageSize() > 1 {
			sql_str := fmt.Sprintf("select count(agentId) %s", after_from_buf.String())
			a.log.Infof("def_func_db_agent.go Find method exec %s params is %+v\n", sql_str, params)
			row := dbAccounts.QueryRow(sql_str, params...)
			var total sql.NullInt64
			err = row.Scan(&total)
			if err != nil {
				a.log.Errorf("def_fun_db_agent.go Find method dbAccounts.QueryRow err. %v\n", err)
				reply.Err = 2
				break
			}
			if total.Valid {
				if total.Int64 < 1 {
					break
				}
				reply.Total = uint32(total.Int64)
			}

			after_from_buf.WriteString(" limit ?,?")
			params = append(params, args.GetStartRow(), args.GetPageSize())
		}

		sql_str := fmt.Sprintf("select d.agentId, d.regionCode, d.agentStatus, d.aLoginName, UNIX_TIMESTAMP(d.agAddTime), d.agentPrice, d.addUseId, u.userName %s", after_from_buf.String())
		a.log.Infof("def_func_db_agent.go Find method exec %s params is %+v\n", sql_str, params)
		rows, err := dbAccounts.Query(sql_str, params...)
		switch {
		case err == sql.ErrNoRows:
			err = nil
			reply.Err = 1
		case err != nil:
			reply.Err = 2
			a.log.Errorf("def_fun_db_agent.go Find method dbAccounts.Query err. %v\n", err)
		default:
			reply.Rows = make([]*grpcmodel.ModelDbRpcAgent, 0)
			for rows.Next() {
				var (
					agentId, agentStatus, addUseId, agAddTime sql.NullInt64
					regionCode, aloginName, userName          sql.NullString
					agentPrice                                sql.NullFloat64
				)
				err := rows.Scan(&agentId, &regionCode, &agentStatus, &aloginName, &agAddTime, &agentPrice, &addUseId, &userName)
				if err != nil {
					reply.Err = 2
					a.log.Errorf("def_fun_db_agent.go Find method rows.Scan err. %v\n", err)
				}
				tmp_agent := &grpcmodel.ModelDbRpcAgent{}
				if addUseId.Valid {
					tmp_agent.AddUseId = uint32(addUseId.Int64)
				}
				if userName.Valid {
					tmp_agent.AddUseName = userName.String
				}
				if agentId.Valid {
					tmp_agent.AgentId = uint32(agentId.Int64)
				}
				if agentStatus.Valid {
					tmp_agent.AgentStatus = uint32(agentStatus.Int64)
				}
				if regionCode.Valid {
					tmp_agent.RegionCode = regionCode.String
				}
				if aloginName.Valid {
					tmp_agent.LoginName = aloginName.String
				}
				if agAddTime.Valid {
					tmp_agent.AddTime = uint64(agAddTime.Int64)
				}
				if agentPrice.Valid {
					tmp_agent.AgentPrice = agentPrice.Float64
				}
				reply.Rows = append(reply.Rows, tmp_agent)
			}
		}
		break
	}
	return
}

//根据用户名查询一个代理信息
func (a *DbRpcAgent) FindUser(ctx context.Context, args *grpcmodel.ModelDbRpcAgentReqFind) (reply *grpcmodel.ModelDbRpcAgentReqFindUser, err error) {
	reply = &grpcmodel.ModelDbRpcAgentReqFindUser{}
	dbAccounts := NewDbProxy().Get(DB_Accounts)
	sql_after_str := bytes.Buffer{}
	sql_after_str.WriteString("from dubagent where agentStatus=1")
	params := make([]interface{}, 0)
	for {
		if args.GetIsRepeat() {
			//让等式不成立
			sql_after_str.WriteString(" and (1=2")
			if args.GetLoginName() != "" {
				sql_after_str.WriteString(" or aLoginName=?")
				params = append(params, args.GetLoginName())
			}
			sql_after_str.WriteString(") limit 1")

			sql_str := fmt.Sprintf("select agentId %s", sql_after_str.String())
			a.log.Infof("def_func_db_agent.go FindUser method exec %s params is %+v\n", sql_str, params)
			row := dbAccounts.QueryRow(sql_str, params...)
			var agentId sql.NullInt64
			err = row.Scan(&agentId)
			if err == sql.ErrNoRows {
				err = nil
				reply.Err = 1
				break
			}
			if err != nil {
				reply.Err = 2
				a.log.Infof("def_func_db_agent.go FindUser method row.Scan err. %v\n", err)
				break
			}
			reply.RepeatId = uint32(agentId.Int64)
			break
		}

		if args.GetLoginName() != "" {
			sql_after_str.WriteString(" and aLoginName=?")
			params = append(params, args.GetLoginName())
		}

		sql_after_str.WriteString(" limit 1")
		sql_str := fmt.Sprintf("select agentId,roleId,regionCode,agentStatus,aLoginName,aLoginPwd,UNIX_TIMESTAMP(agAddTime),UNIX_TIMESTAMP(agEditTime),agentPrice %s", sql_after_str.String())
		a.log.Infof("def_func_db_agent.go FindUser method exec %s params is %+v\n", sql_str, params)
		row := dbAccounts.QueryRow(sql_str, params...)
		var (
			agentId, roleId, agentStatus, agAddTime, agEditTime sql.NullInt64
			regionCode, aLoginName, aLoginPwd                   sql.NullString
			agentPrice                                          sql.NullFloat64
		)
		err = row.Scan(&agentId, &roleId, &regionCode, &agentStatus, &aLoginName, &aLoginPwd, &agAddTime, &agEditTime, &agentPrice)

		switch {
		case err == sql.ErrNoRows:
			err = nil
			reply.Err = 1
		case err != nil:
			reply.Err = 2
			a.log.Errorf("def_fun_db_agent.go FindUser method dbAccounts.QueryRow err. %v\n", err)
		default:
			model := &grpcmodel.ModelDbRpcAgent{}
			if agentId.Valid {
				model.AgentId = uint32(agentId.Int64)
			}
			if roleId.Valid {
				model.RoleId = uint32(roleId.Int64)
			}
			if regionCode.Valid {
				model.RegionCode = regionCode.String
			}
			if aLoginName.Valid {
				model.LoginName = aLoginName.String
			}
			if aLoginPwd.Valid {
				model.LoginPwd = aLoginPwd.String
			}
			if agentStatus.Valid {
				model.AgentStatus = uint32(agentStatus.Int64)
			}
			if agentPrice.Valid {
				model.AgentPrice = agentPrice.Float64
			}
			if agAddTime.Valid {
				model.AddTime = uint64(agAddTime.Int64)
			}
			if agEditTime.Valid {
				model.EditTime = uint64(agEditTime.Int64)
			}
			reply.ModelDbRpcAgent = model
		}
		break
	}
	return
}

//添加一个代理信息
func (a *DbRpcAgent) Add(ctx context.Context, args *grpcmodel.ModelDbRpcAgentReqAdd) (reply *grpcmodel.ModelDbRpcAgentResAdd, err error) {
	reply = &grpcmodel.ModelDbRpcAgentResAdd{}
	dbAccounts := NewDbProxy().Get(DB_Accounts)

	sql_pre_buf := bytes.Buffer{}
	sql_pre_buf.WriteString("insert into dubagent (roleId, agentStatus, agAddTime, agEditTime, agentPrice, addUseId")
	sql_aft_buf := bytes.Buffer{}
	sql_aft_buf.WriteString(") values (?,?,now(),now(),?,?")
	params := make([]interface{}, 0)
	params = append(params, args.GetModelDbRpcAgent().GetRoleId())
	params = append(params, args.GetModelDbRpcAgent().GetAgentStatus())
	params = append(params, args.GetModelDbRpcAgent().GetAgentPrice())
	params = append(params, args.GetModelDbRpcAgent().GetAddUseId())

	if args.GetModelDbRpcAgent().GetRegionCode() != "" {
		sql_pre_buf.WriteString(", regionCode")
		sql_aft_buf.WriteString(",?")
		params = append(params, args.GetModelDbRpcAgent().GetRegionCode())
	}
	if args.GetModelDbRpcAgent().GetLoginName() != "" {
		sql_pre_buf.WriteString(", aLoginName")
		sql_aft_buf.WriteString(",?")
		params = append(params, args.GetModelDbRpcAgent().GetLoginName())
	}
	if args.GetModelDbRpcAgent().GetLoginPwd() != "" {
		sql_pre_buf.WriteString(", aLoginPwd")
		sql_aft_buf.WriteString(",?")
		params = append(params, args.GetModelDbRpcAgent().GetLoginPwd())
	}
	sql_aft_buf.WriteString(")")
	sql_pre_buf.WriteString(sql_aft_buf.String())

	sql_str := sql_pre_buf.String()
	a.log.Infof("def_func_db_agent.go Add method exec %s params is %+v\n", sql_str, params)
	res, err := dbAccounts.Exec(sql_str, params...)

	for {
		if err != nil {
			reply.Err = 2
			a.log.Errorf("def_fun_db_agent.go Add method dbAccounts.Exec err. %v\n", err)
			break
		}

		up_id, err := res.LastInsertId()
		if err != nil {
			reply.Err = 2
			break
		}

		reply.AgentId = uint32(up_id)
		reply.Err = 0
		break
	}
	return
}

var d_dbRpcAgent *DbRpcAgent

func NewDbRpcAgent() *DbRpcAgent {
	if d_dbRpcAgent == nil {
		d_dbRpcAgent = &DbRpcAgent{
			log: utils.NewLogger(),
		}
	}
	return d_dbRpcAgent
}
